/* Developed by Vinh, Nguyen Hong <mansofta@gmail.com>
 * Copyright HIENDAI SOFTWARE COMPANY 2004
 * http://www.hiendai.com.vn
 * contact@hiendai.com.vn
*/
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
using System.Collections;

namespace MarcXmlParser {

	public class CRecord//:IDisposable
	{
	
	protected	XmlDocument ptCurrentDoc;
	protected	XmlNode ptCurrentRootNode;
    protected bool _is_Changed = false;

	public CRecord()
		{
			ptCurrentDoc=new XmlDocument();
            ptCurrentDoc.NodeChanged += new XmlNodeChangedEventHandler(ptCurrentDoc_Changed);
            ptCurrentDoc.NodeInserted += new XmlNodeChangedEventHandler(ptCurrentDoc_Changed);
            ptCurrentDoc.NodeRemoved += new XmlNodeChangedEventHandler(ptCurrentDoc_Changed);		
			ptCurrentDoc.LoadXml("<record><leader></leader></record>"); 
			ptCurrentRootNode=ptCurrentDoc.SelectSingleNode("./*[local-name() ='record']"); 		
		}
    private void ptCurrentDoc_Changed(object sender, EventArgs e)
    {
        _is_Changed = true;
    }
    public bool is_Changed
    {
        get
        {
            return _is_Changed;
        }
        set
        {
            _is_Changed = value;
        }
    }
	public void Sort()
	{
			ArrayList CfAL = new ArrayList();
			ArrayList DfAL = new ArrayList();
			CControlfields Cfs= new CControlfields(ref ptCurrentRootNode);
			for(int i=0;i<Cfs.Count;i++)
			{
				CfAL.Add(Cfs.Controlfield(i).OuterXml);
				Cfs.Remove(i);
			}
			CDatafields Dfs=new CDatafields(ref ptCurrentRootNode);
			for(int j=0;j<Dfs.Count;j++)
			{
				DfAL.Add(Dfs.Datafield(j).OuterXml);
				Dfs.Remove(j);
			}
			CfAL.Sort();
			DfAL.Sort();
			for(int i=0;i<CfAL.Count;i++)
			{
				CControlfield Cf=new CControlfield();
				Cf.load_Xml(CfAL[i].ToString());
				Cfs.Add(Cf);
			}
			for(int j=0;j<DfAL.Count;j++)
			{
				CDatafield Df=new CDatafield();
				Df.load_Xml(DfAL[j].ToString());
				Df.Sort();
				Dfs.Add(Df);
			}

	}
	public void ReConstruct()
		{
			ptCurrentDoc.LoadXml("<record><leader></leader></record>"); 
			ptCurrentRootNode=ptCurrentDoc.SelectSingleNode("./*[local-name() ='record']"); 					
		}
	public  bool load_RootNode(ref XmlNode ptRecordRootNode)
		{
			ptCurrentRootNode=ptRecordRootNode;
            if (ptCurrentRootNode != null)
				return true;
			else
				return false;
		}
	 public bool load_Xml(String MarcRecordText)
		{
            MarcRecordText=MarcRecordText.Replace("xmlns=\"http://www.loc.gov/MARC21/slim\"", "");
			ptCurrentDoc.LoadXml(MarcRecordText);            
			ptCurrentRootNode=ptCurrentDoc.SelectSingleNode("./*[local-name() ='record']");
            if (ptCurrentRootNode != null)
            {
                if (ptCurrentRootNode.Attributes.Count > 0)
                {
                    ptCurrentRootNode.Attributes.RemoveAll();
                    int icount = ptCurrentRootNode.Attributes.Count;

                }
                return true;
            }
            else
            {
                return false;
            }
		}	
	 public bool load_File(String MarcXmlFileName)
		{
			XmlTextReader reader = new XmlTextReader(MarcXmlFileName);
			reader.WhitespaceHandling = WhitespaceHandling.None;
            try
            {
                ptCurrentDoc.Load(reader);
                ptCurrentRootNode = ptCurrentDoc.SelectSingleNode("./*[local-name() ='record']");
                if (ptCurrentRootNode != null)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            finally
            {
                reader.Close();
            }
		}	
	 public String OuterXml
	 {
		 get
		 {
			return ptCurrentRootNode.OuterXml ;  			
		 }	 
	 }
	 public XmlNode RootNode
	 {
		get
		{
			return ptCurrentRootNode;
		}
	 }
	 public CDatafields Datafields
	 {			
		 get
		 {
			return new CDatafields(ref ptCurrentRootNode);	 
		 }
	 }
	 public CControlfields Controlfields
	 {
		 get
		 {
			return new CControlfields(ref ptCurrentRootNode);
		 }		
	 }
	 public String Leader
	 {
		 set
		 {
			XmlNode ptEditNode;
			XmlNode ptLeaderNode;
			ptLeaderNode=ptCurrentRootNode.SelectSingleNode("./*[local-name() ='leader']");
            if (ptLeaderNode != null)//Leader Node have been Existed
			{
				if (ptLeaderNode.HasChildNodes) //child text node have been existed
				{
					ptEditNode=ptLeaderNode.FirstChild;
					ptEditNode.Value=value; 					
				} else // Create new text node then add to the parent node
				{
					ptLeaderNode.AppendChild(ptCurrentRootNode.OwnerDocument.CreateTextNode(value));
				}			
			} else
			{
					ptLeaderNode=ptCurrentRootNode.OwnerDocument.CreateElement("leader");
					ptLeaderNode.AppendChild(ptCurrentRootNode.OwnerDocument.CreateTextNode(value));
					ptCurrentRootNode.AppendChild(ptLeaderNode);		
			}		 		 
		 }
		 get
		 {
			XmlNode ptLeaderNode;
			ptLeaderNode=ptCurrentRootNode.SelectSingleNode("./*[local-name() ='leader']");
            if (ptLeaderNode != null)//Leader Node have been Existed
			{
					return ptLeaderNode.InnerText; 
			} else
			{
					ptLeaderNode=ptCurrentRootNode.OwnerDocument.CreateElement("leader");
					ptLeaderNode.AppendChild(ptCurrentRootNode.OwnerDocument.CreateTextNode(""));
					ptCurrentRootNode.AppendChild(ptLeaderNode);		
					return ptLeaderNode.InnerText; 
			}		 
		 }	 
	 }

	public void set_LeaderValueByPos(String sValue,int StartPos, int EndPos)
		{
			XmlNode ptEditNode;
			StringBuilder Sb = new StringBuilder();
			StringBuilder SbValue= new StringBuilder(sValue);
			int Valen=sValue.Length; 
			if (Valen==0)
				return;
			if (StartPos>EndPos)
				return;
			if (Valen>(EndPos+1-StartPos))//Value length greater than space
				{
					SbValue.Remove(EndPos+1-StartPos,Valen-(EndPos+1-StartPos)); 
				}
			if (Valen<(EndPos+1-StartPos))//Value length smaller than space
				{
					SbValue.Insert(Valen," ",(EndPos+1-StartPos)-Valen); 
				}

			XmlNode ptLeaderNode;
			ptLeaderNode=ptCurrentRootNode.SelectSingleNode("./*[local-name() ='leader']");
            if (ptLeaderNode != null)//Leader Node have been Existed
			{
				if (ptLeaderNode.HasChildNodes) //child text node have been existed
				{
					ptEditNode=ptLeaderNode.FirstChild;
					Sb.Append(ptEditNode.InnerText); 
					if(Sb.Length<EndPos+1)//not enough space
					{
						Sb.Append(' ',(EndPos+Valen+1)-Sb.Length);  																									
					}				
					Sb.Insert(StartPos,SbValue.ToString());
					Sb.Remove(EndPos+1,SbValue.Length);  
					ptEditNode.Value=Sb.ToString(); 					
				} else // Create new text node then add to the parent node
				{
					Sb.Append(' ',EndPos+Valen+1);  																									
					Sb.Insert(StartPos,SbValue.ToString());
					ptLeaderNode.AppendChild(ptCurrentRootNode.OwnerDocument.CreateTextNode(Sb.ToString()));
				}			
			} else
			{
					ptLeaderNode=ptCurrentRootNode.OwnerDocument.CreateElement("leader");
					Sb.Append(' ',EndPos+Valen+1);  																									
					Sb.Insert(StartPos,SbValue.ToString());
					ptLeaderNode.AppendChild(ptCurrentRootNode.OwnerDocument.CreateTextNode(Sb.ToString()));
					ptCurrentRootNode.AppendChild(ptLeaderNode);								
			}
		}

        public String get_LeaderValueByPos(int StartPos, int EndPos)
		{
			XmlNode ptLeaderNode;
			StringBuilder Sb = new StringBuilder();				
			String TempStr;
			ptLeaderNode=ptCurrentRootNode.SelectSingleNode("./*[local-name() ='leader']");
			if((EndPos+1-StartPos)<=0) 
				return "";
            if (ptLeaderNode != null)
				Sb.Append(ptLeaderNode.InnerText);
			else
				return "";
			if (Sb.Length>=StartPos)
			{
				if (Sb.Length<(EndPos+1))
				{
					EndPos=Sb.Length-1;
				}
				TempStr=Sb.ToString();				
				return TempStr.Substring(StartPos,(EndPos+1-StartPos));  
			}else
			{
				return "";
			}
		}
		public String XsltFile_Transform(String XslFileName)
		{			
			XslCompiledTransform xslt = new XslCompiledTransform();
            //XsltSettings xsltSet=new XsltSettings();
            //xsltSet.EnableScript= true;
            xslt.Load(XslFileName);//, xsltSet,null);
			//// Transform the file and output an HTML string.			
			XmlNodeReader xmlNodeRdr = new XmlNodeReader(ptCurrentRootNode); 
			StringBuilder Sb=new StringBuilder();
            XmlWriterSettings xsetting = new XmlWriterSettings();
            xsetting.ConformanceLevel = ConformanceLevel.Auto;          
            xslt.Transform(xmlNodeRdr, null, XmlWriter.Create(Sb, xsetting), null);
			return Sb.ToString();	
		}
		public String XsltUri_Transform(String XslUri)
		{			
			XslCompiledTransform xslt = new XslCompiledTransform(); 					
			xslt.Load(XmlReader.Create(XslUri));
			//// Transform the file and output an HTML string.			
			XmlNodeReader xmlNodeRdr = new XmlNodeReader(ptCurrentRootNode); 
			StringBuilder Sb=new StringBuilder();			
			xslt.Transform(xmlNodeRdr,null, XmlWriter.Create(Sb), null);
			return Sb.ToString();	
		}
		public void Save(String XmlFileName)
		{	
				XmlDocument tempDoc=new XmlDocument();
				tempDoc.LoadXml(ptCurrentRootNode.OuterXml);					
				tempDoc.PreserveWhitespace = true; 
                XmlWriter xW = XmlWriter.Create(XmlFileName);
                tempDoc.Save(xW);
                xW.Flush();
                xW.Close();
				tempDoc.RemoveAll();
		}

        public void MoveUp()
        {
            ptCurrentRootNode.ParentNode.InsertBefore(ptCurrentRootNode,ptCurrentRootNode.PreviousSibling);
        }
        public void MoveDown()
        {
            ptCurrentRootNode.ParentNode.InsertAfter(ptCurrentRootNode, ptCurrentRootNode.NextSibling);
        }
};
}